"""JWT 与密码工具函数。"""

from datetime import datetime, timedelta, timezone
from typing import Any, Dict, Optional

from jose import JWTError, jwt
import bcrypt

from backend.common.config import config_manager


def hash_password(plain_password: str) -> str:
    """生成密码哈希。"""
    # Ensure password is encoded to UTF-8
    password_bytes = plain_password.encode('utf-8')
    # bcrypt automatically handles the 72 byte limit
    salt = bcrypt.gensalt()
    hashed = bcrypt.hashpw(password_bytes, salt)
    return hashed.decode('utf-8')


def verify_password(plain_password: str, password_hash: str) -> bool:
    """校验密码。"""
    if not plain_password or not password_hash:
        return False
    try:
        password_bytes = plain_password.encode('utf-8')
        hash_bytes = password_hash.encode('utf-8')
        return bcrypt.checkpw(password_bytes, hash_bytes)
    except Exception:
        return False


def _create_token(data: Dict[str, Any], expires_delta: timedelta, token_type: str) -> str:
    """内部方法：生成带过期时间及类型的 JWT。"""
    to_encode = data.copy()
    expire = datetime.now(timezone.utc) + expires_delta
    to_encode.update({"exp": expire, "type": token_type})
    secret = config_manager.auth.jwt_secret or "change-me"
    algorithm = config_manager.auth.jwt_algorithm or "HS256"
    return jwt.encode(to_encode, secret, algorithm=algorithm)


def create_access_token(data: Dict[str, Any], expires_minutes: Optional[int] = None) -> str:
    """生成访问令牌。"""
    minutes = expires_minutes or config_manager.auth.jwt_expire_minutes or 30
    return _create_token(data, timedelta(minutes=minutes), token_type="access")


def create_refresh_token(data: Dict[str, Any], expires_days: Optional[int] = None) -> str:
    """生成刷新令牌。"""
    days = expires_days or config_manager.auth.jwt_refresh_expire_days or 7
    return _create_token(data, timedelta(days=days), token_type="refresh")


def decode_token(token: str) -> Dict[str, Any]:
    """解析并验证 JWT。"""
    secret = config_manager.auth.jwt_secret or "change-me"
    algorithm = config_manager.auth.jwt_algorithm or "HS256"
    payload = jwt.decode(token, secret, algorithms=[algorithm])
    return payload


__all__ = [
    "hash_password",
    "verify_password",
    "create_access_token",
    "create_refresh_token",
    "decode_token",
]
